package com.snda.storage.service.sdk;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;

import java.io.File;
import java.io.InputStream;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.snda.storage.service.sdk.xml.BucketSummary;
import com.snda.storage.service.sdk.xml.Content;
import com.snda.storage.service.sdk.xml.CreateBucketConfiguration;
import com.snda.storage.service.sdk.xml.ListAllMyBucketsResult;
import com.snda.storage.service.sdk.xml.ListBucketResult;
import com.snda.storage.service.sdk.xml.LocationConstraint;
import com.sun.jersey.api.client.WebResource;

/**
 * 
 * @author wangzijian@snda.com
 * 
 */
public class StorageServiceClient implements StorageService {

	private WebResource webResource;

	@Override
	public List<Bucket> listBuckets() {
		ListAllMyBucketsResult listAllMyBucketsResult = webResource.get(ListAllMyBucketsResult.class);
		return ImmutableList.copyOf(transform(listAllMyBucketsResult, new Function<BucketSummary, Bucket>() {
			@Override
			public Bucket apply(BucketSummary summary) {
				return new Bucket(
						summary.getName(), 
						summary.getLocation(), 
						summary.getCreation());
			}
		}));
	}

	@Override
	public ObjectListing listObjects(String bucketName) {
		checkNotNull(bucketName);
		return listObjects(bucketName, Criteria.EMPTY);
	}

	@Override
	public ObjectListing listObjects(String bucketName, Criteria criteria) {
		checkNotNull(bucketName);
		checkNotNull(criteria);
		WebResource bucketResource = webResource.path(bucketName);
		if (criteria.getPrefix() != null) {
			bucketResource = bucketResource.queryParam(Criteria.PARAMETER_PREFIX, criteria.getPrefix());
		}
		if (criteria.getMarker() != null) {
			bucketResource = bucketResource.queryParam(Criteria.PARAMETER_MARKER, criteria.getMarker());
		}
		if (criteria.getDelimiter() != null) {
			bucketResource = bucketResource.queryParam(Criteria.PARAMETER_DELIMITER, criteria.getDelimiter());
		}
		if (criteria.getMaxKeys() != null) {
			bucketResource = bucketResource.queryParam(Criteria.PARAMETER_MAX_KEYS, criteria.getMaxKeys().toString());
		}
		ListBucketResult listBucketResult = bucketResource.get(ListBucketResult.class);
		return new ObjectListing.Builder()
				.bucketName(listBucketResult.getBucketName())
				.nextMarker(listBucketResult.getNextMarker())
				.truncated(listBucketResult.getTruncated())
				.prefix(listBucketResult.getPrefix())
				.marker(listBucketResult.getMarker())
				.maxKeys(listBucketResult.getMaxKeys())
				.delimiter(listBucketResult.getDelimiter())
				.commonPrefixes(listBucketResult.getCommonPrefixes())
				.objectSummaries(transform(listBucketResult.getContents(), new Function<Content, ObjectSummary>(){
					@Override
					public ObjectSummary apply(Content content) {
						return new ObjectSummary.Builder()
								.key(content.getKey())
								.size(content.getSize())
								.entityTag(content.getEntityTag())
								.lastModified(content.getLastModified())
								.build();
					}
				}))
				.build();
	}

	@Override
	public ObjectListing listObjectsOfNextBatch(ObjectListing previous) {
        if (!previous.isTruncated()) {
            return new ObjectListing.Builder()
            	.bucketName(previous.getBucketName())
            	.delimiter(previous.getDelimiter())
            	.marker(previous.getMarker())
            	.maxKeys(previous.getMaxKeys())
            	.prefix(previous.getPrefix())
            	.truncated(false)
            	.build();
        }
		return listObjects(previous.getBucketName(), new Criteria.Builder()
			.prefix(previous.getPrefix())
			.marker(previous.getNextMarker())
			.delimiter(previous.getDelimiter())
			.maxKeys(previous.getMaxKeys())
			.build());
	}

	@Override
	public void createBucket(String bucketName) {
		checkNotNull(bucketName);
		webResource.path(bucketName).put();
	}

	@Override
	public void createBucket(String bucketName, Location region) {
		checkNotNull(bucketName);
		checkNotNull(region);
		webResource.path(bucketName).put(new CreateBucketConfiguration(region.toString()));

	}

	@Override
	public Location getBucketLocation(String bucketName) {
		checkNotNull(bucketName);
		return webResource.path(bucketName).queryParam("location", "")
				.get(LocationConstraint.class)
				.getValue();
	}

	@Override
	public void deleteBucket(String bucketName) {
		checkNotNull(bucketName);
		webResource.path(bucketName).delete();
	}

	@Override
	public void putObject(String bucketName, InputStream inputStream, Metadata objectMetadata) {
		// TODO Auto-generated method stub

	}

	@Override
	public void putObject(String bucketName, String key, File file) {
		// TODO Auto-generated method stub

	}

	@Override
	public void putObjects(String bucketName, File directory) {
		// TODO Auto-generated method stub

	}

	@Override
	public Metadata getObjectMetadata(String bucketName, String key) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public InputStream getObjectContent(String bucketName, String key) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public StorageObject getObject(String bucketName, String key) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void deleteObject(String bucketName, String key) {
		// TODO Auto-generated method stub

	}

}
